#ifndef AVALON_SIZEDECLARATIVEREADER_HPP
#define AVALON_SIZEDECLARATIVEREADER_HPP
#include <boost/cstdint.hpp>
#include "Avalon/Base/Handle.hpp"
#include "Avalon/IO/Reader.hpp"

namespace Avalon {
namespace IO {

  /*! \class SizeDeclariveReader
   *  \brief Reads data whose size is declared at the beginning.
   */
  class SizeDeclarativeReader : public Reader {
    public:

      //! Constructs a SizeDeclarativeReader.
      /*!
        \param source The source to read from.
      */
      SizeDeclarativeReader(Carry<Reader> source);

      virtual ~SizeDeclarativeReader();

      virtual void Read(void* destination, int size,
        Out<Threading::Async<int> > sizeRead);

      virtual void Read(Buffer* destination, int size,
        Out<Threading::Async<int> > sizeRead);

      using Reader::Read;

    private:
      struct SizeReadParameters {
        Buffer* m_buffer;
        void* m_destination;
        int m_size;
      };
      struct DataReadParameters {
        void* m_destination;
        boost::uint32_t m_totalSize;
        boost::uint32_t m_sizeToRead;
      };
      Handle<Reader> m_source;
      boost::uint32_t m_sizeRemaining;
      char* m_sizeReadIterator;
      Threading::Async<int> m_sizeRead;
      Threading::Async<int> m_dataRead;
      Threading::Async<int>* m_result;
      SizeReadParameters m_sizeReadParameters;
      DataReadParameters m_dataReadParameters;

      void OnSizeRead();
      void OnDataRead();
  };
}
}

#endif // AVALON_SIZEDECLARATIVEREADER_HPP
